package net.gdface.utils;

import static com.google.common.base.Preconditions.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.ForwardingMap;
import com.google.common.collect.Iterables;

import net.gdface.reflection.MethodUtils;
import net.gdface.reflection.generics.TypeVisitor;

/**
 * 反射工具类
 * @author guyadong
 *
 */
public class ReflectionUtils {
	public static final String PROP_CLASSNAME = "className";
	public static final String PROP_STATICMETHODNAME = "staticMethodName";
	public static final String PROP_PARAMETERTYPES = "parameterTypes";
	public static final String PROP_CONSTRUCTORARGS = "constructorArgs";
	public static final String PROP_CONSTRUCTORPARAMS = "constructorParams";
	private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
	private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
	private static final Set<String> overridableObjectMethods = new HashSet<>(Arrays.asList("clone","finalize","hashCode","equals","toString"));
	public ReflectionUtils() {
	}
	private static class ParameterMap extends ForwardingMap<String,Object>{
		private final Map<String, Object> delegate;
		public ParameterMap(Map<String, Object> delegate) {
			super();
			if(null == delegate){
				this.delegate = Collections.emptyMap();
			}else{
				this.delegate = delegate;
			}
		}
		@Override
		protected Map<String, Object> delegate() {
			return delegate;
		}
		@SuppressWarnings("unchecked")
		public final <T> T of(String key,T defaultValue){
			checkArgument(null != key);
			Object value = delegate.get(key);
			try{
				return null == value ? defaultValue: (T) value;
			}catch(ClassCastException e){
				throw new IllegalArgumentException("invalid parameter: " + key + ",caused by " + e.getMessage());
			}
		}
		public final <T> T of(String key){
			return of(key,null);
		}
	}
	@SuppressWarnings("unchecked")
	public static <T> Class<? extends T> getInstanceClass(Class<T> superClass,String instanceClassName) 
			throws ClassNotFoundException{
		checkArgument(null != superClass && !Strings.isNullOrEmpty(instanceClassName));
		Class<?> instanceClass = (Class<?>) Class.forName(instanceClassName);
		checkInstanceClass(superClass,instanceClass);
		return  (Class<? extends T>)instanceClass;
	}
	public static <T> T getInstance(Class<T> superClass,Map<String,Object> params) 
			throws NoSuchMethodException, ClassNotFoundException{
		ParameterMap paramMap = new ParameterMap(params);
		String clazzName = paramMap.of(PROP_CLASSNAME);
		Class<? extends T> instanceClass = getInstanceClass(superClass,clazzName);
		String staticMethodName =paramMap.of(PROP_STATICMETHODNAME);
		if(null != staticMethodName){
			try{
				return getInstanceByStaticMethod(superClass,instanceClass,staticMethodName);
			}catch(NoSuchMethodException e){
				// 找不到静态方法则尝试用构造方法创建实例
			}
		}
		if(paramMap.containsKey(PROP_CONSTRUCTORPARAMS)){
			LinkedHashMap<Class<?>,Object> constructorParams = paramMap.of(PROP_CONSTRUCTORPARAMS);
			return getInstanceByConstructor(superClass,instanceClass,constructorParams);
		}else{
			Class<?>[] parameterTypes = paramMap.of(PROP_PARAMETERTYPES);
			Object[] ctorArgs = paramMap.of(PROP_CONSTRUCTORARGS);
			return getInstanceByConstructor(superClass,instanceClass,parameterTypes,ctorArgs);
		}
	}
	private static void checkInstanceClass(Class<?> superClass,Class<?> instanceClass){
		checkArgument(null != superClass && null != instanceClass);
		checkArgument(!instanceClass.isInterface() && superClass.isAssignableFrom(instanceClass),
				"%s not a implemenation of %s",instanceClass.getName(),superClass.getSimpleName());
		checkArgument(!Modifier.isAbstract(instanceClass.getModifiers()),
				"%s is abstract class",instanceClass.getName());
		checkArgument(Modifier.isStatic(instanceClass.getModifiers()) || null == instanceClass.getDeclaringClass(),
				"%s is not static class",instanceClass.getName());
	}
	public static <T> T getInstanceByConstructor(Class<T> superClass,Class<? extends T> instanceClass,Class<?>[] parameterTypes,Object[] constructorArgs) 
			throws NoSuchMethodException{
		checkInstanceClass(superClass,instanceClass);
		parameterTypes = MoreObjects.firstNonNull(parameterTypes, EMPTY_CLASS_ARRAY);
		constructorArgs = MoreObjects.firstNonNull(constructorArgs, EMPTY_OBJECT_ARRAY);
		checkArgument(parameterTypes.length == constructorArgs.length);
		try{
			Constructor<? extends T> ctor = instanceClass.getConstructor(parameterTypes);
			try {
				return ctor.newInstance(constructorArgs);
			} catch (Exception e) {
				Throwables.throwIfUnchecked(e);
				throw new RuntimeException(e);
			}
		} finally{}
	}
	public static <T> T getInstanceByConstructor(Class<T> superClass,Class<? extends T> instanceClass,LinkedHashMap<Class<?>,Object> constructorParams) 
			throws NoSuchMethodException{
		checkInstanceClass(superClass,instanceClass);
		constructorParams = MoreObjects.firstNonNull(constructorParams, new LinkedHashMap<Class<?>,Object>());
		Class<?>[] parameterTypes = constructorParams.keySet().toArray(new Class<?>[constructorParams.size()]);
		Object[] initargs = constructorParams.values().toArray(new Object[constructorParams.size()]);
		Constructor<? extends T> ctor = instanceClass.getConstructor(parameterTypes);
		try {
			return ctor.newInstance(initargs);
		} catch (InvocationTargetException e) {
			Throwables.throwIfUnchecked(e.getTargetException());
			throw new RuntimeException(e.getTargetException());
		}catch (Exception e) {
			Throwables.throwIfUnchecked(e);
			throw new RuntimeException(e);
		}
	}
	@SuppressWarnings("unchecked")
	public static <T> T getInstanceByStaticMethod(Class<T> superClass,Class<? extends T> instanceClass,String staticMethodName) 
			throws NoSuchMethodException{
		checkArgument(!Strings.isNullOrEmpty(staticMethodName));
		checkInstanceClass(superClass,instanceClass);
		try {
			Method method = instanceClass.getMethod(staticMethodName);
			checkArgument(Modifier.isStatic(method.getModifiers()),"%s is not a static method",method.toString());
			checkArgument(superClass.isAssignableFrom(method.getReturnType()),"unexpect return type %s",method.getReturnType().toString());
			try{
				return (T) method.invoke(null);
			}catch(ClassCastException e){
				throw new IllegalArgumentException(
						String.format("invalid return type of static method %s caused by %s",method.toString(),e.getMessage()));
			}
		} catch(NoSuchMethodException e){
			throw e;
		}catch (Exception e) {
			Throwables.throwIfUnchecked(e);
			throw new RuntimeException(e);
		}
	}
	/**
	 * 反射获取{@code object}的私有成员
	 * @param object
	 * @param name
	 * @return 成员对象
	 */
	@SuppressWarnings("unchecked")
	public static <T> T valueOfField(Object object,String name){
		try {
			Field field = getField(checkNotNull(object,"object is null").getClass(),checkNotNull(name,"name is null"));
			field.setAccessible(true);
			return (T) field.get(object);
		} catch (Exception e) {
			Throwables.throwIfUnchecked(e);
			throw new RuntimeException(e);
		}
	}
	/**
	 * 反射修改{@code object}的私有成员
	 * @param object 对象
	 * @param name 成员名
	 * @param value 成员值
	 */
	public static void setValueOfField(Object object,String name,Object value){
		try {
			Field field = getField(checkNotNull(object,"object is null").getClass(),checkNotNull(name,"name is null"));
			field.setAccessible(true);
			boolean isfinal = (field.getModifiers() & Modifier.FINAL) == Modifier.FINAL;
			String modifiersName = "modifiers";
			if(isfinal){
				Field modifiers = field.getClass().getDeclaredField(modifiersName);
				// 去除final 修饰符
				modifiers.setAccessible(true);
				modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);				
			}
			field.set(object,value);
			if(isfinal){
				Field modifiers = field.getClass().getDeclaredField(modifiersName);
				// 恢复final 修饰符
				modifiers.setInt(field, field.getModifiers() | Modifier.FINAL);
			}
		} catch (Exception e) {
			Throwables.throwIfUnchecked(e);
			throw new RuntimeException(e);
		}
	}
	/**
	 * 反射修改{@code clazz}的静态私有成员
	 * @param clazz 类型
	 * @param name 成员名
	 * @param value 成员值
	 */
	public static void setValueOfStaticField(Class<?> clazz,String name,Object value){
		try {
			Field field = getField(checkNotNull(clazz,"clazz is null"),checkNotNull(name,"name is null"));
			field.setAccessible(true);
			boolean isfinal = (field.getModifiers() & Modifier.FINAL) == Modifier.FINAL;
			String modifiersName = "modifiers";
			if(isfinal){
				Field modifiers = field.getClass().getDeclaredField(modifiersName);
				// 去除final 修饰符
				modifiers.setAccessible(true);
				modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);				
			}
			field.set(clazz,value);
			if(isfinal){
				// 恢复final 修饰符
				Field modifiers = field.getClass().getDeclaredField(modifiersName);
				modifiers.setAccessible(true);
				modifiers.setInt(field, field.getModifiers() | Modifier.FINAL);
			}
		} catch (Exception e) {
			Throwables.throwIfUnchecked(e);
			throw new RuntimeException(e);
		}
	}
	/**
	 * 返回输入的方法重写的父类的方法
	 * @param input
	 * @return 如果{@code input}为{@code null}或非重写父类方法则返回{@code null}
	 */
	public static Method getOverride(Method input){
		if(input == null){
			return null;
		}
		int modifier = input.getModifiers();
		if(Modifier.isStatic(modifier) || Modifier.isPrivate(modifier)){
			return null;
		}
		Class<?> declaringClass = input.getDeclaringClass();
		if(Object.class.equals(declaringClass)){
			return null;
		}		
		Method om = getOverrideObjectMethod(input);
		if(om != null){
			return om;
		}
		
		for (Class<?> interfaceType : declaringClass.getInterfaces()) {
			Method matched = MethodUtils.getMatchingAccessibleMethod(interfaceType, input.getName(), input.getParameterTypes(),
					true, MethodUtils.OVERRIDABLE_METHOD_FILTER);
			if(null != matched) {
				return matched;
			}
		}
		Class<?> superclass = declaringClass.getSuperclass();
		if (superclass != Object.class && superclass != null) {
			Method matched = MethodUtils.getMatchingAccessibleMethod(superclass, input.getName(), input.getParameterTypes(), 
					true, MethodUtils.OVERRIDABLE_METHOD_FILTER);
			if(null != matched ) {
				return matched;
			}
		}
		return null;
	}
	/**
	 * 返回输入的方法重写的顶级父类的方法
	 * @param input
	 * @return 如果{@code input}为{@code null}或非重写父类方法则返回{@code null}
	 * @see #getOverride(Method)
	 */
	public static Method getOverrideTop(Method input){
		Method om = input;
		Method sm ;
		while((sm = getOverride(om)) != null){
			om = sm;
		}
		if(Objects.equal(om, input)){
			return null;
		}
		return om;
	}
	/**
	 * 如果输入方法({@code input})为重写方法则返回重写的顶级父类的方法,否则返回{@code input}
	 * @param input
	 * @return 如果{@code input}为{@code null}或非重写父类方法则返回{@code null}
	 * @see #getOverride(Method)
	 */
	public static Method overrideTopOrSelf(Method input){
		Method om = getOverrideTop(input);
		return om == null ? input : om;
	}
	/**
	 * 如果输入的方法为重写{@link Object}类的方法("clone","finalize","hashCode","equals","toString")
	 * 则返回{@link Object}类对应的方法,否则返回{@code null}
	 * @param input
	 * @return {@code input}为{@code null}返回{@code null}
	 */
	public static Method getOverrideObjectMethod(Method input){
		if(input == null){
			return null;
		}
		int modifier = input.getModifiers();
		if(Modifier.isStatic(modifier) || Modifier.isPrivate(modifier)){
			return null;
		}
		String name = input.getName();
		if(!overridableObjectMethods.contains(name)){
			return null;
		}
		try {
			Method om = Object.class.getDeclaredMethod(name, input.getParameterTypes());
			if(om.getReturnType().equals(input.getReturnType())){
				return om;
			}
		} catch (NoSuchMethodException e) {
		}
		return null;
	}
	/**
	 * 
	 * 判断方法是否为重写Object的方法
	 * @param input
	 */
	public static boolean isOverrideObjectMethod(Method input){
		return getOverrideObjectMethod(input) != null;
	}
	/**
	 * 判断{@code input}是否为残存的影子方法<br>
	 * 如果在方法声明的类{@link Method#getDeclaringClass()}中使用根据{@code input}的名字和参数查找方法找到的方法与{@code input}不相同,
	 * 即为因残存的被重写的父类方法,因返回类型不相同而残存
	 * @param input
	 * @return {@code input}为{@code null}返回{@code false} 
	 */
	public static boolean isOverrideShadow(Method input){
		if( input != null){
			Class<?> declaringClass = input.getDeclaringClass();
			if(Object.class.equals(declaringClass)){
				return false;
			}
			try {
				Method self = declaringClass.getMethod(input.getName(), input.getParameterTypes());
				return !self.equals(input);
			} catch (Throwable e) {
				Throwables.throwIfUnchecked(e);
				throw new RuntimeException(e);
			}
		}
		return false;
	}
	/**
	 * (递归)如果指定方法为覆盖(override)或实现接口方法，则自底向上查找此方法覆盖的方法所在的父类或接口类,
	 * 返回第一个找到覆盖方法所声明的类,如:
	 * A为接口类，B实现了A的方法test，C继承B,覆盖了test，则此方法调用返回为B
	 * @param declaringClass 声明方法的类
	 * @param methodName 方法名
	 * @param parameterTypes 方法参数
	 * @return 被覆盖(override)方法所在的类,非覆盖方法返回{@code null},输入参数为{@code null}则返回{@code null}
	 */
	public static Class<?> getOverrideClassRecursive(Class<?> declaringClass,final String methodName,final Class<?>...parameterTypes) {
		if(null != declaringClass && null != methodName && null != parameterTypes) {
			List<Class<?>> impls = Arrays.asList(declaringClass.getInterfaces());
			Optional<Class<?>> found = Iterables.tryFind(impls, new Predicate<Class<?>>() {

				@Override
				public boolean apply(Class<?> c) {
					try {
						c.getMethod(methodName, parameterTypes);
						return true;
					} catch (NoSuchMethodException | SecurityException e) {
						return false;
					}
				}
			});
			if(found.isPresent()) {
				return found.get();
			}
			Class<?> superClass = declaringClass.getSuperclass();
			try {
				if(null !=superClass){
					superClass.getMethod(methodName, parameterTypes);
					return superClass;					
				}
			} catch (NoSuchMethodException | SecurityException e) {
			}
			return getOverrideClassRecursive(superClass,methodName,parameterTypes);
			
		}
		return null;
	}
	/**
	 * 如果指定方法为覆盖(override)或实现接口方法，则自底向上查找此方法覆盖的方法所在的父类或接口类,
	 * 返回最顶层被覆盖方法所声明的类,如：
	 * A为接口类，B实现了A的方法test，C继承B,覆盖了test，则此方法调用返回为A
	 * @param declaringClass 声明方法的类
	 * @param methodName 方法名
	 * @param parameterTypes 方法参数
	 * @return 被覆盖(override)方法所在的类,非覆盖方法返回{@code null},输入参数为{@code null}则返回{@code null}
	 */
	public static Class<?> getOverrideTopClass(Class<?> declaringClass,String methodName,Class<?>...parameterTypes) {
		Class<?> last = declaringClass;
		Class<?> clazz;
		for(;;) {
			clazz = getOverrideClassRecursive(last,methodName,parameterTypes);
			if(null == clazz){
				if(declaringClass != last){
					clazz = last;					
				}
				break;
			}
			last = clazz;
		}		
		return clazz;
	}
	/**
	 * 如果指定方法为覆盖(override)或实现接口方法，则自底向上查找此方法覆盖的方法所在的父类或接口类,
	 * 返回第一个找到覆盖方法所声明的类,如:
	 * A为接口类，B实现了A的方法test，C继承B,覆盖了test，则此方法调用返回为B
	 * @param method 
	 * @return 被覆盖(override)方法所在的类,非覆盖方法返回{@code null},输入参数为{@code null}则返回{@code null}
	 * @see #getOverrideClassRecursive(Class, String, Class...)
	 */
	public static Class<?> getOverrideClass(Method method) {
		return null == method ? null : getOverrideClassRecursive(method.getDeclaringClass(),method.getName(),method.getParameterTypes());
	}

	/**
	 * 如果指定方法为覆盖(override)或实现接口方法，则自底向上查找此方法覆盖的方法所在的父类或接口类,
	 * 返回最顶层被覆盖方法所声明的类,如：
	 * A为接口类，B实现了A的方法test，C继承B,覆盖了test，则此方法调用返回为A
	 * @param method 
	 * @return 被覆盖(override)方法所在的类,非覆盖方法返回{@code null},输入参数为{@code null}则返回{@code null}
	 * @see #getOverrideTopClass(Class, String, Class...)
	 */
	public static Class<?> getOverrideTopClass(Method method) {
		return null == method ? null : getOverrideTopClass(method.getDeclaringClass(),method.getName(),method.getParameterTypes());
	}
	/**
	 * 返回方法是否为覆盖方法
	 * @param method
	 */
	public static boolean isOverride(Method method){
		return null != getOverrideClass(method);
	}
	/**
	 * 递归返回类型为声明的字段<br>
	 * 如果当前中没有找到则向上到父类查找,输入参数为{@code null}返回{@code null}
	 * @param clazz
	 * @param name
	 * @throws NoSuchFieldException 没有找到指定的成员 
	 */
	public static Field getField(Class<?> clazz,String name) throws NoSuchFieldException{
		if(null != clazz&& null != name){
			try {
				return clazz.getDeclaredField(name);
			} catch (NoSuchFieldException e) {
				Class<?> superClass = clazz.getSuperclass();
				if(null != superClass && !Object.class.equals(superClass)){
					return getField(superClass,name);
				}
				throw e;
			}
		}
		return null;
	}
	/**
	 * @see #getField(Class, String)
	 * @param clazz
	 * @param name
	 * @return 没有找到返回{@code null}
	 */
	public static Field getFieldUnchecked(Class<?> clazz,String name){
		try {
			return getField(clazz,name);
		} catch (NoSuchFieldException e) {
			return null;
		}
	}
	/**
	 * [递归]返回指定类型上定义所有泛型变量及对应的实际的泛型参数的映射
	 * @param <M>
	 * @param clazz
	 * @param typeVariables [out]保存数据结果的映射对象 ，如果指定类型及所有父类型没有泛型变量则不会输出任何结果
	 * @return always typeVariables
	 * @since 2.10.1
	 */
	public static<M extends Map<TypeVariable<?>, Type> >  M getTypeVariables(Class<?> clazz,M typeVariables) {
		Class<?> superClass;
		if(null != clazz && (superClass = clazz.getSuperclass()) != null && null != typeVariables) {
			TypeVariable<?>[] typeParameters = superClass.getTypeParameters();
			if(typeParameters.length>0) {
				ParameterizedType genericSuperClass = (ParameterizedType) clazz.getGenericSuperclass();
				Type[] typeArgs = ((ParameterizedType) genericSuperClass).getActualTypeArguments();
				for(int i=0;i<typeParameters.length;++i) {
					typeVariables.put(typeParameters[i], typeArgs[i]);
				}
				return getTypeVariables(clazz.getSuperclass(),typeVariables);
			}
		}
		return typeVariables;
	}
	/**
	 * 返回指定类型上定义所有泛型变量及对应的泛型参数的映射，如果指定类型及所有父类型没有泛型变量则返回空
	 * @param clazz
	 * @return 保存数据结果的映射对象 
	 * @since 2.10.1
	 */
	public static LinkedHashMap<TypeVariable<?>, Type> getTypeVariables(Class<?> clazz) {
		return getTypeVariables(clazz,new LinkedHashMap<TypeVariable<?>, Type>());
	}
	/**
	 * 返回归一化的泛型变量-泛型参数映射<br>
	 * 如果Value是泛型变量({@link TypeVariable})则尝试以之为Key在表中查找对应的实际的泛型参数({@link ParameterizedType}或Class )，
	 * 如果找到则修改Value.
	 * @param clazz
	 * @param checkExisting 为{@code true}进行严格检查，如果映射中的Value是泛型变量且在映射中找不对应的泛型参数则抛出异常
	 * @return 泛型变量及对应的泛型参数的映射
	 * @see #getTypeVariables(Class, Map)
	 * @since 2.10.1
	 */
	public static Map<TypeVariable<?>, Type> getNormalizedTypeVariables(Class<?> clazz, boolean checkExisting) {
		 LinkedHashMap<TypeVariable<?>, Type> typeVariables = getTypeVariables(clazz);
		for(TypeVariable<?> typeVariable:typeVariables.keySet().toArray(new TypeVariable[typeVariables.size()])) {
			/** 泛型变量对应的实际泛型参数 */
			Type actualType = typeVariables.get(typeVariable);
			/** 如果Value是泛型变量，将值作为Key 循环查找直到找不到或类型不是泛型变量 */
			while(actualType instanceof TypeVariable) {
				actualType = typeVariables.get(actualType);
			}
			if(null == actualType) {
				/** 如果没有找到泛型变量对象的实际泛型参数且checkExisting为true抛出异常 */
				if(checkExisting) {
					StringBuilder builder = new StringBuilder("actualTypeArguments of ")
							.append(typeName(clazz)).append(":\r\n");
					for(Entry<TypeVariable<?>, Type> entry:typeVariables.entrySet()) {
						builder.append(typeName(entry.getKey()))
								.append("-->").append(typeName(entry.getValue())).append(":\r\n");
					}
					throw new IllegalArgumentException(String.format(
							"NOT FOUND actual TypeArgument for %s\n%s",
								typeName(typeVariable),builder));
				}

			}else if(!(actualType  instanceof TypeVariable)) {
				/** 将找到实际泛型参数替换原泛型变量值 */
				typeVariables.put(typeVariable, actualType);
			}
		}
		return typeVariables;
	}
	/**
	 * 检查类型中是否有类型变量{@link TypeVariable},如果有返回{@code true}
	 * @param type
	 * @since 2.10.2
	 */
	public static boolean hasTypeVariable(Type type) {
		return new RejectTypeVariable(type).hasTypeVariable;
	}
	/**
	 * 检查类型中是否有类型变量{@link TypeVariable},如果有抛出异常
	 * @param type
	 * @return always type
	 * @throws IllegalArgumentException 有类型变量
	 * @since 2.10.2
	 */
	public static Type rejectTypeVariable(Type type) throws IllegalArgumentException {
		return new RejectTypeVariable(type,true).type;
	}
	/**
	 * 类型变量类型变量{@link TypeVariable}检查工作
	 * @since 2.10.2
	 *
	 */
	public static class RejectTypeVariable extends TypeVisitor{
		final Type type;
		final boolean throwIfTrue;
		protected boolean hasTypeVariable = false;
		public RejectTypeVariable(Type runtimeType,boolean throwIfFound) {
			this.type = runtimeType;
			this.throwIfTrue = throwIfFound;
			try {
				visit(runtimeType);
			} catch (IllegalArgumentException e) {
				hasTypeVariable = true;
				if(throwIfTrue) {
					throw e;
				}
			}
		}
		public RejectTypeVariable(Type runtimeType) {
			this(runtimeType, false);
		}
		public boolean isHasTypeVariable() {
			return hasTypeVariable;
		}

		@Override
		protected void visitTypeVariable(TypeVariable<?> type) {
				throw new IllegalArgumentException(
						type + "contains a type variable and is not safe for the operation");
		}
	}
	private static String typeName(Type type) {
		String name = TypeNameUtils.getTypeName(type, true);
		if(type instanceof TypeVariable) {
			/** 输出定义泛型变量的类型 */
			name +="@"+typeName((Type) ((TypeVariable<?>)type).getGenericDeclaration());
		}
		return name;
	}	
}
